GOPATH required all Go code to live in a single workspace directory with no versioning. Go modules introduced go.mod for explicit versioning, reproducible builds, and support for any directory structure.
All Go code must live under $GOPATH/src/
No versioning — go get always fetches the latest commit
No reproducible builds — different developers could get different dependency versions
Cannot have multiple versions of the same dependency
Effectively deprecated — only use for very old codebases
go.mod declares module name, Go version, and direct dependencies with versions
go.sum contains cryptographic hashes for all dependencies — guarantees reproducibility
Module proxy (proxy.golang.org) caches modules — works even if the original repo is deleted
Private modules: set GONOSUMCHECK and GOMODCACHE for internal packages
Minimum version selection (MVS): Go always picks the minimum satisfying version, not the latest